<?php
// +----------------------------------------------------------------------
// | 萤火商城系统 [ 致力于通过产品和服务，帮助商家高效化开拓市场 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 这不是一个自由软件，不允许对程序代码以任何形式任何目的的再发行
// +----------------------------------------------------------------------
// | Author: 萤火科技 <admin@yiovo.com>
// +----------------------------------------------------------------------
declare (strict_types=1);

namespace app\common\service\order;

use app\common\exception\BaseException;
use app\common\library\helper;
use app\common\model\OrderSub as OrderSubModel;
use app\common\model\User as UserModel;
use app\common\model\wxapp\Setting as WxappSettingModel;
use app\common\model\user\BalanceLog as BalanceLogModel;
use app\common\enum\order\PayType as OrderPayTypeEnum;
use app\common\enum\user\balanceLog\Scene as SceneEnum;
use app\common\library\wechat\WxPay;
use app\common\service\bangdou\BdPay as BdPayService;
use app\common\service\BaseService;

/**
 * 订单退款服务类
 * Class Refund
 * @package app\common\service\order
 */
class Refund extends BaseService
{
    /**
     * 执行订单退款
     * @param $order
     * @param null $money
     * @return bool
     * @throws \cores\exception\BaseException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function execute($order, $money = null): bool
    {
        // 1.微信支付退款
        if ($order['pay_type'] == OrderPayTypeEnum::WECHAT) {
            if($order['bd_type'] == OrderPayTypeEnum::BALANCE){//余额和微信支付组合支付退款
                $ordersub                = OrderSubModel::getOrderSubBy($order['order_parent_id']);//获去取支付信息
                $payMoney = bcadd($ordersub['pay_money'], $ordersub['deduction_value'], 2);
                if ($money > $payMoney) {//退款金额大于支付金额
                    throwError('退款金额大于支付金额');
                    return false;
                }
                $ordermoney = helper::bcadd($order['pay_cash'], $order['deduction_value']);
                if ($ordermoney < $money) {
                    throwError('退款金额有误');
                    return false;
                }

                if($order['pay_cash'] == 0.00){
                    is_null($money) && $money = $order['deduction_value'];
                    return $this->balance($order,$money);//退余额
                }
                //优先退现金
                if($money>$order['pay_cash']){//现金不够退余额
                    $order['deduction_value'] = helper::bcsub($money,$order['pay_cash']); //68、67两行位置不能换
                    $money = $order['pay_cash'];
                }else{
                    $money = $order['pay_cash'];
                    $order['deduction_value'] = 0;
                }
                $order['pay_price'] = $ordersub['pay_original_money'];//父订单微信实际支付总金额
                if($this->wxpay($order,$money)){//退微信
                    if($order['deduction_value']>0){
                        return $this->balance($order,$order['deduction_value']);//退余额
                    }
                    return true;
                }
            }else{
                return BdPayService::bangdouRefund($order,$order['transaction_id'],$money);//微信、三券退款
            }
        }
        // 2.余额支付退款
        if ($order['pay_type'] == OrderPayTypeEnum::BALANCE) {
            is_null($money) && $money = $order['deduction_value'];
            return $this->balance($order, $money);
        }
        return false;
    }

    /**
     * 余额支付退款
     * @param $order
     * @param $money
     * @return bool
     */
    private function balance($order, $money): bool
    {
        // 回退用户余额
        UserModel::setIncBalance((int)$order['user_id'], (float)$money);
        // 记录余额明细
        BalanceLogModel::add(SceneEnum::REFUND, [
            'user_id'         => (int)$order['user_id'],
            'money'           => $order['pay_cash'],
            'correlation_id'  => $order['order_id'],
            'bd_type'         => $order['bd_type'],
            'deduction_value' => $money,
        ], ['order_no' => $order['order_no']]);
        /*BalanceLogModel::add(SceneEnum::REFUND, [
            'user_id' => $order['user_id'],
            'money' => $money,
        ], ['order_no' => $order['order_no']]);*/
        return true;
    }

    /**
     * 微信支付退款
     * @param $order
     * @param string|null $money
     * @return bool
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \cores\exception\BaseException
     */
    private function wxpay($order, ?string $money): bool
    {
        $wxConfig = WxappSettingModel::getWxappConfig($order['store_id']);
        $WxPay = new WxPay($wxConfig, $order['store_id']);
        return $WxPay->refund($order['transaction_id'], $order['pay_price'], $money);
    }
}